from django_redis import get_redis_connection
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import Serializer

from oauth.models import OAuthQQUser
from oauth.utils import check_openid
from users.models import User


class QQUserSerializer(Serializer):
    """
    QQ登录创建用户序列化器
    """
    openid = serializers.CharField(label='openid', write_only=True)
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$',
                                    write_only=True)
    password = serializers.CharField(label='密码', max_length=20, min_length=8,
    write_only = True)
    sms_code = serializers.CharField(label='短信验证码', write_only=True)

    def validate(self, attrs):
        encrypted_openid = attrs['openid']  # 获取这个openid是已经加密处理的
        # 调用 util.py文件里的check_openid方法进行解密
        openid = check_openid(encrypted_openid)
        if not openid:  # 校验openid是否被篡改或过期
            raise ValidationError({'message':'openid无效'})
        # 修改字典中的openid 让字典中的openid是已经校验通过的openid
        attrs['openid'] = openid

        mobile = attrs['mobile']
        sms_code = attrs['sms_code']
        password = attrs['password']

        # 校验短信验证码
        redis_conn = get_redis_connection('sms_codes')
        real_sms_code = redis_conn.get('sms_%s' % mobile)
        if not real_sms_code:
            raise serializers.ValidationError('短信验证码无效')
        if real_sms_code.decode() != sms_code:
            raise serializers.ValidationError('短信验证码错误')

        try:  # 查询要绑定的用户, 如果存在，校验密码是否正确
            # 根据手机号去查询要绑定的用户
            user = User.objects.get(mobile=mobile)
            if not user.check_password(password):
                raise serializers.ValidationError('密码错误')
        except User.DoesNotExist:
            # 用户不存在, 则自动新增一个美多用户, 再进行绑定 以手机号作为用户名
            user = User.objects.create_user(
                username=mobile,
                password=password,
                mobile=mobile,
            )

        # 将认证后的user放进校验字典中，绑定关联时用到
        # 因为上面已经拿到了user。不存在我们也创建了
        attrs['user'] = user
        return attrs

    def create(self, validated_data):
        # 获取校验的用户
        user = validated_data.get('user')
        # 从字典对象里取出openid,因为qq登陆成功返回了code
        openid = validated_data.get('openid')

        # 绑定openid和美多用户： 新增一条数据到映射表中
        OAuthQQUser.objects.create(
            openid=openid,
            user=user
        )
        return user  # 返回绑定的美多用户对象

